package me.itsoo.artemis.framework.core.collect;

import java.io.Serializable;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

/**
 * ImmutableMap
 *
 * @author zxy
 * @version 0.0.1
 * @since 2023/5/29
 */
public class ImmutableMap<K, V> implements Map<K, V>, Serializable {

    private static final long serialVersionUID = 8976388615544707654L;

    private final LinkedHashMap<K, V> selfMap;

    private ImmutableMap(LinkedHashMap<K, V> selfMap) {
        this.selfMap = selfMap;
    }

    /**
     * builder
     *
     * @param <K> K
     * @param <V> V
     * @return Builder
     */
    public static <K, V> Builder<K, V> builder() {
        return new Builder<>();
    }

    @Override
    public int size() {
        return selfMap.size();
    }

    @Override
    public boolean isEmpty() {
        return selfMap.isEmpty();
    }

    @Override
    public boolean containsKey(Object key) {
        return selfMap.containsKey(key);
    }

    @Override
    public boolean containsValue(Object value) {
        return selfMap.containsValue(value);
    }

    @Override
    public V get(Object key) {
        return selfMap.get(key);
    }

    @Override
    public V put(K key, V value) {
        throw new UnsupportedOperationException();
    }

    @Override
    public V remove(Object key) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void putAll(Map<? extends K, ? extends V> m) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void clear() {
        throw new UnsupportedOperationException();
    }

    @Override
    public Set<K> keySet() {
        return selfMap.keySet();
    }

    @Override
    public Collection<V> values() {
        return selfMap.values();
    }

    @Override
    public Set<Entry<K, V>> entrySet() {
        return selfMap.entrySet();
    }

    /**
     * ImmutableMapBuilder
     *
     * @param <K> K
     * @param <V> V
     */
    public static class Builder<K, V> {

        private final LinkedHashMap<K, V> buildMap;

        public Builder() {
            this(16);
        }

        Builder(int initialCapacity) {
            this.buildMap = new LinkedHashMap<>(initialCapacity);
        }

        public Builder<K, V> put(K key, V value) {
            this.buildMap.put(key, value);
            return this;
        }

        public Builder<K, V> putAll(Map<K, ? extends V> map) {
            this.buildMap.putAll(map);
            return this;
        }

        public Map<K, V> build() {
            return new ImmutableMap<>(buildMap);
        }
    }
}
